package com.enjoyor.soa.traffic.server.efoms.dubbo.listener;

import com.enjoyor.soa.traffic.api.dto.MessageInfoDto;
import com.enjoyor.soa.traffic.api.dto.efoms.PingResultDto;
import com.enjoyor.soa.traffic.api.service.dubbo.CallbackListener;
import com.enjoyor.soa.traffic.core.efoms.domain.DeviceDetailInfo;
import com.enjoyor.soa.traffic.core.efoms.domain.DeviceStatusInfo;
import com.enjoyor.soa.traffic.core.efoms.domain.DeviceWranInfo;
import com.enjoyor.soa.traffic.core.efoms.domain.PingConnectReal;
import com.enjoyor.soa.traffic.core.efoms.domain.WranTacticsInfo;
import com.enjoyor.soa.traffic.core.efoms.enums.EnumDicPublic;
import com.enjoyor.soa.traffic.core.efoms.helper.GetObjectHelper;
import com.enjoyor.soa.traffic.core.efoms.service.IDevStatusInfoService;
import com.enjoyor.soa.traffic.core.efoms.service.IDeviceWranInfoService;
import com.enjoyor.soa.traffic.server.efoms.common.Global;
import com.enjoyor.soa.traffic.server.efoms.dubbo.invoke.DubboPingCallBackInvoke;
import com.enjoyor.soa.traffic.server.efoms.dubbo.manage.ManagePingConnectRealService;
import com.enjoyor.soa.traffic.server.efoms.dubbo.manage.ManageWranTacticsService;
import com.enjoyor.soa.traffic.server.efoms.helper.ObjectSwitchHelper;
import com.enjoyor.soa.traffic.util.enums.EnumOprType;
import com.enjoyor.soa.traffic.util.handler.BasicMsgHandler;
import com.enjoyor.soa.traffic.util.helper.TimeHelper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.*;

@Async
@Order(1)
@Component
public class DubboPingCallBackListener implements CommandLineRunner {
    String keyName = "efoms_serverT";
    
    @Autowired
    private DubboPingCallBackInvoke callBackInvoke;
    @Autowired
    private ManagePingConnectRealService pingConnectRealService;
    @Autowired
    private IDevStatusInfoService devStatusInfoService;
	@Autowired
    private IDeviceWranInfoService deviceWranInfoService;
	@Autowired
    private ManageWranTacticsService manageWranTacticsService;
    
	//默认操作人
  	String personName = "ping程序";
  	//网络报警类型
  	String unpingWranTypeCode = EnumDicPublic.DEV_WRAN_TYPE_UNPING.getKey();
  	String unpingWranTypeName = EnumDicPublic.DEV_WRAN_TYPE_UNPING.getValue();
  	String packWranTypeCode = EnumDicPublic.DEV_WRAN_TYPE_HIGHPACK.getKey();
  	String packWranTypeName = EnumDicPublic.DEV_WRAN_TYPE_HIGHPACK.getValue();
  	String respWranTypeCode = EnumDicPublic.DEV_WRAN_TYPE_HIGHRESP.getKey();
  	String respWranTypeName = EnumDicPublic.DEV_WRAN_TYPE_HIGHRESP.getValue();
  	//状态异常报警等级
  	String pingWranLevelCode = EnumDicPublic.DEV_WRAN_LEVEL_SERIOUS.getKey();
  	String pingWranLevelName = EnumDicPublic.DEV_WRAN_LEVEL_SERIOUS.getValue();
	
    @Override
    public void run(String... args) throws Exception {
        startCallBack();
    }

    private void startCallBack() throws InterruptedException {
        addListener(keyName);
        while (true) {
            try {
                if (callBackInvoke != null && !callBackInvoke.isActive(keyName)) {
                    addListener(keyName);
                }
            } catch (Exception e) {
                StackTraceElement StackTrace = Thread.currentThread().getStackTrace()[1];
                //LogInfoHelper.writeErrorLogInfo("设备运维回调", StackTrace, e);
            } finally {
                Thread.sleep(10000);
            }
        }
    }

    CallbackListener listener;
    private CallbackListener getListener() {
        if (listener == null) {
            listener = new CallbackListener() {
                @Override
                @SuppressWarnings("unchecked")
                public void update(MessageInfoDto msg) {
                    handler.handle(msg); 
                }
            };
        }
        return listener;
    }

    private void addListener(String name) {
        try {
        	callBackInvoke.addListener(name, getListener());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    BasicMsgHandler<MessageInfoDto> handler = new BasicMsgHandler<MessageInfoDto>() {
        /**
         * 获取回调，将报警信息存储到数据库并进行分析
         * @param result
         * @return
         */
		@Override
        @SuppressWarnings("unchecked")
        protected boolean process(MessageInfoDto result) {
        	if(EnumOprType.EFOMS_PING_DATA.equals(result.getMsgType())) {
        		try {
                    List<PingResultDto> pingResultList = (List<PingResultDto>)result.getObject();
                    if(null != pingResultList && pingResultList.size() > 0) {
                    	//存储网络连接数据
						List<PingConnectReal> pingConnectRealList = ObjectSwitchHelper
								.pingResultToConnectRealList(pingResultList);
						pingConnectRealService.insertPingConnectBatch(pingConnectRealList, "ping程序");
						//分析网络连接数据，更新设备状态、生成报警信息
						String startT = "接收start**********************" + TimeHelper.dateToLongString();
						pingConnectHandle(pingConnectRealList); 
                    }
                } catch (Exception e) {
                    StackTraceElement StackTrace = Thread.currentThread().getStackTrace()[1];
                    List listParam = Arrays.asList(result);
                    //LogInfoHelper.writeErrorLogInfo("处理缉查布控回调", StackTrace, listParam, e, ResultPojo.class);
                }
        	}
            return true;
        }
    };
    //分析网络连接数据，更新设备状态、根据报警策略生成报警信息
    public void pingConnectHandle(List<PingConnectReal> pingConnectRealList) {
    	String devTypeCodeSea = pingConnectRealList.get(0).getDevTypeCode();
    	List<WranTacticsInfo> wranTacticsListPack = manageWranTacticsService.selectWranTacticsList(
    			packWranTypeCode, devTypeCodeSea, null);
    	List<WranTacticsInfo> wranTacticsListResp = manageWranTacticsService.selectWranTacticsList(
    			respWranTypeCode, devTypeCodeSea, null);
    	String packWranLevelCode = "";
    	String packWranLevelName = "";
    	String respWranLevelCode = "";
    	String respWranLevelName = "";
    	for(PingConnectReal pingConnect : pingConnectRealList) {
			String devCategoryCode = pingConnect.getDevCategoryCode();
			String devCategoryName = GetObjectHelper.getNameByCategoryCode(devCategoryCode);
			String devTypeCode = pingConnect.getDevTypeCode();
			String devTypeName = GetObjectHelper.getNameByTypeCode(devTypeCode);
			String devId = pingConnect.getDevId();
			double packageProb = pingConnect.getPackageProb();
			double responseTime = pingConnect.getResponseTime();
			String key = devTypeCode + "-" + devId;
			DeviceDetailInfo deviceDetailInfo = Global.DeviceInfoPool.get(key);
			String devName = "";
			if(null != deviceDetailInfo) {
				devName = deviceDetailInfo.getDevName();
			}else {
				return;
			}
			Boolean isPingConnect = pingConnect.getIsPingConnect();
			Boolean isHighPackage = false;
			Boolean isHighResponse = false;
			//报警策略
			if(isPingConnect) {
				//根据策略判断是否高丢包
				if(null != wranTacticsListPack && wranTacticsListPack.size() > 0) {
					for(WranTacticsInfo wranTacticsInfo : wranTacticsListPack) {
						int minValue = wranTacticsInfo.getMinValue();
						if(packageProb >= (double)minValue) {
							isHighPackage = true;
							packWranLevelCode = wranTacticsInfo.getWranLevelCode();
					    	packWranLevelName = wranTacticsInfo.getWranLevelName();
							break;
						}
					}
				}
				//根据策略判断是否高响应
				if(null != wranTacticsListResp && wranTacticsListResp.size() > 0) {
					for(WranTacticsInfo wranTacticsInfo : wranTacticsListResp) {
						int minValue = wranTacticsInfo.getMinValue();
						if(responseTime >= (double)minValue) {
							isHighResponse = true;
					    	respWranLevelCode = wranTacticsInfo.getWranLevelCode();
					    	respWranLevelName = wranTacticsInfo.getWranLevelName();
							break;
						}
					}
				}
				
			}else {
				isHighPackage = null;
				isHighResponse = null;
			}
			
			DeviceStatusInfo deviceStatusPool = Global.DevStatusPool.get(key);
			//更新设备状态表以及对应内存
			if(null == deviceStatusPool) { 
				//DeviceDetailInfo deviceDetailInfo = deviceDetailInfoService.selectDeviceDetailInfoById(typeCode, devId);
				DeviceStatusInfo deviceStatusInfo = new DeviceStatusInfo(devCategoryCode, devCategoryName, 
						devTypeCode, devTypeName, devId, devName, isPingConnect, isHighPackage, isHighResponse);
				devStatusInfoService.insertDevStatusInfoOnly(deviceStatusInfo, personName);
				Global.DevStatusPool.put(key, deviceStatusInfo);
			}else if(isPingConnect != deviceStatusPool.getIsPingConnect() || isHighPackage != deviceStatusPool.getIsHighPackage()
					|| isHighResponse != deviceStatusPool.getIsHighResponse()) {
				deviceStatusPool.setIsPingConnect(isPingConnect);
				deviceStatusPool.setIsHighPackage(isHighPackage);
				deviceStatusPool.setIsHighResponse(isHighResponse);
				devStatusInfoService.updateDevStatusInfo(deviceStatusPool, personName);
				Global.DevStatusPool.put(key, deviceStatusPool);
			}
			//根据策略生成网络不通报警数据
			DeviceWranInfo devicePingWranInfo = deviceWranInfoService.selectDeviceWranInfoByKey(devCategoryCode, 
					devTypeCode, devId, unpingWranTypeCode, "0");
			if(null == devicePingWranInfo) {
				if(!isPingConnect) {
					//新增报警数据
					String wranContent = "网络连接不通报警";
					DeviceWranInfo deviceWranInsert = new DeviceWranInfo(devCategoryCode, devCategoryName, devTypeCode, 
							devTypeName, devId, devName, unpingWranTypeCode, unpingWranTypeName, pingWranLevelCode, 
							pingWranLevelName, wranContent);
					deviceWranInfoService.insertDeviceWranInfo(deviceWranInsert, personName);
				}
			}else {
				//更新报警数据，正常则删除实时报警且增加历史数据
				if(!isPingConnect) {
					deviceWranInfoService.updateTimeByWranType(devCategoryCode, devTypeCode, devId, 
							unpingWranTypeCode, null, personName);
				}else{
					String devWranId = devicePingWranInfo.getDevWranId();
					deviceWranInfoService.deleteDeviceWranInfo(devWranId, personName);
					deviceWranInfoService.insertDeviceWranInfoHis(devicePingWranInfo, personName);
				}
			}
			if(isPingConnect) {
				//根据策略生成网络高丢包报警数据 packageProb
				DeviceWranInfo devicePackWranInfo = deviceWranInfoService.selectDeviceWranInfoByKey(devCategoryCode, 
						devTypeCode, devId, packWranTypeCode, "0");
				if(null == devicePackWranInfo) {
					if(isHighPackage) {
						//新增报警数据
						String wranContent = "网络丢包率为" + packageProb + "%";
						DeviceWranInfo deviceWranInsert = new DeviceWranInfo(devCategoryCode, devCategoryName, devTypeCode, 
								devTypeName, devId, devName, packWranTypeCode, packWranTypeName, packWranLevelCode, 
								packWranLevelName, wranContent);
						deviceWranInfoService.insertDeviceWranInfo(deviceWranInsert, personName);
					}
				}else {
					//更新报警数据，正常则删除实时报警且增加历史数据
					if(isHighPackage) {
						deviceWranInfoService.updateTimeByWranType(devCategoryCode, devTypeCode, devId, 
								packWranTypeCode, null, personName);
					}else{
						String devWranId = devicePackWranInfo.getDevWranId();
						deviceWranInfoService.deleteDeviceWranInfo(devWranId, personName);
						deviceWranInfoService.insertDeviceWranInfoHis(devicePackWranInfo, personName);
					}
				}
				//根据策略生成网络高响应报警数据responseTime
				DeviceWranInfo deviceRespWranInfo = deviceWranInfoService.selectDeviceWranInfoByKey(devCategoryCode, 
						devTypeCode, devId, respWranTypeCode, "0");
				if(null == deviceRespWranInfo) {
					if(isHighResponse) {
						//新增报警数据
						String wranContent = "网络平均响应时间为" + responseTime + "ms";
						DeviceWranInfo deviceWranInsert = new DeviceWranInfo(devCategoryCode, devCategoryName, devTypeCode, 
								devTypeName, devId, devName, respWranTypeCode, respWranTypeName, respWranLevelCode, 
								respWranLevelName, wranContent);
						deviceWranInfoService.insertDeviceWranInfo(deviceWranInsert, personName);
					}
				}else {
					//更新报警数据，正常则删除实时报警且增加历史数据
					if(isHighResponse) {
						deviceWranInfoService.updateTimeByWranType(devCategoryCode, devTypeCode, devId, 
								respWranTypeCode, null, personName);
					}else{
						String devWranId = deviceRespWranInfo.getDevWranId();
						deviceWranInfoService.deleteDeviceWranInfo(devWranId, personName);
						deviceWranInfoService.insertDeviceWranInfoHis(deviceRespWranInfo, personName);
					}
				}
			}
		}
    }
}
